﻿using SD.Common;
using SD.Infrastructure.EntityBase;
using SlamDunk.ValueObjects.Enums;
using SlamDunk.ValueObjects.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SlamDunk.MES.Domain.Entities.StockContext
{
    /// <summary>
    /// 库存单据
    /// </summary>
    public abstract class StockOrder : AggregateRootEntity, ICheckable
    {
        #region # 构造器

        #region 00.无参构造器
        /// <summary>
        /// 无参构造器
        /// </summary>
        protected StockOrder()
        {
            //初始化导航属性
            this.Details = new HashSet<StockOrderDetail>();

            //默认值
            this.CheckStatus = CheckStatus.Unchecked;
        }
        #endregion

        #region 01.创建库存单据构造器
        /// <summary>
        /// 创建库存单据构造器
        /// </summary>
        /// <param name="orderNo">单据编号</param>
        /// <param name="orderName">单据名称</param>
        /// <param name="stockOrderClassId">库存单据类Id</param>
        /// <param name="directionType">出入库方向类型</param>
        /// <param name="sourceOrderType">源单据类型</param>
        /// <param name="sourceOrderId">源单据Id</param>
        /// <param name="sourceOrderName">源单据名称</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        protected StockOrder(string orderNo, string orderName, Guid stockOrderClassId, StockDirectionType directionType, SourceOrderType? sourceOrderType, string sourceOrderId, string sourceOrderName, Guid? facilityId, string description)
            : this()
        {
            base.Number = orderNo;
            base.Name = orderName;
            this.StockOrderClassId = stockOrderClassId;
            this.DirectionType = directionType;
            this.SourceOrderType = sourceOrderType;
            this.SourceOrderId = sourceOrderId;
            this.SourceOrderName = sourceOrderName;
            this.FacilityId = facilityId;
            this.Description = description;

            //初始化关键字
            this.InitKeywords();
        }
        #endregion

        #endregion

        #region # 属性

        #region 库存单据类Id —— Guid StockOrderClassId
        /// <summary>
        /// 库存单据类Id
        /// </summary>
        public Guid StockOrderClassId { get; private set; }
        #endregion

        #region 出/入库方向类型 —— StockDirectionType DirectionType
        /// <summary>
        /// 出/入库方向类型
        /// </summary>
        public StockDirectionType DirectionType { get; private set; }
        #endregion

        #region 源单据类型 —— SourceOrderType? SourceOrderType
        /// <summary>
        /// 源单据类型
        /// </summary>
        public SourceOrderType? SourceOrderType { get; private set; }
        #endregion

        #region 源单据Id —— string SourceOrderId
        /// <summary>
        /// 源单据Id
        /// </summary>
        public string SourceOrderId { get; private set; }
        #endregion

        #region 源单据名称 —— string SourceOrderName
        /// <summary>
        /// 源单据名称
        /// </summary>
        public string SourceOrderName { get; private set; }
        #endregion

        #region 工厂模型Id —— Guid? FacilityId
        /// <summary>
        /// 工厂模型Id
        /// </summary>
        public Guid? FacilityId { get; private set; }
        #endregion

        #region 提审人账号 —— string SubmitterAccount
        /// <summary>
        /// 提审人账号
        /// </summary>
        public string SubmitterAccount { get; set; }
        #endregion

        #region 提审人姓名 —— string SubmitterName
        /// <summary>
        /// 提审人姓名
        /// </summary>
        public string SubmitterName { get; set; }
        #endregion

        #region 审核状态 —— CheckStatus CheckStatus
        /// <summary>
        /// 审核状态
        /// </summary>
        public CheckStatus CheckStatus { get; set; }
        #endregion

        #region 审核意见 —— string CheckedRemark
        /// <summary>
        /// 审核意见
        /// </summary>
        public string CheckedRemark { get; set; }
        #endregion

        #region 审核人账号 —— string CheckerAccount
        /// <summary>
        /// 审核人账号
        /// </summary>
        public string CheckerAccount { get; set; }
        #endregion

        #region 审核人姓名 —— string CheckerName
        /// <summary>
        /// 审核人姓名
        /// </summary>
        public string CheckerName { get; set; }
        #endregion

        #region 审核时间 —— DateTime? CheckedTime
        /// <summary>
        /// 审核时间
        /// </summary>
        public DateTime? CheckedTime { get; set; }
        #endregion

        #region 描述 —— string Description
        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; private set; }
        #endregion

        #region 导航属性 - 库存单据明细集 —— ICollection<StockOrderDetail> Details
        /// <summary>
        /// 导航属性 - 库存单据明细集
        /// </summary>
        public virtual ICollection<StockOrderDetail> Details { get; private set; }
        #endregion

        #endregion

        #region # 方法

        #region 修改库存单据 —— void UpdateInfo(Guid? facilityId, string description)
        /// <summary>
        /// 修改库存单据
        /// </summary>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        protected void UpdateInfo(Guid? facilityId, string description)
        {
            #region # 验证

            if (this.CheckStatus == CheckStatus.Checking)
            {
                throw new InvalidOperationException("审核中的单据不可修改！");
            }
            if (this.CheckStatus == CheckStatus.Passed)
            {
                throw new InvalidOperationException("审核通过的单据不可修改！");
            }

            #endregion

            this.FacilityId = facilityId;
            this.Description = description;

            //初始化关键字
            this.InitKeywords();
        }
        #endregion

        #region 设置单据明细 —— void SetDetails(StockOrderDetail detail)
        /// <summary>
        /// 设置单据明细
        /// </summary>
        /// <param name="details">单据明细集</param>
        public void SetDetails(IEnumerable<StockOrderDetail> details)
        {
            details = details?.ToArray() ?? new StockOrderDetail[0];

            this.ClearDetails();
            if (details.Any())
            {
                this.Details.AddRange(details);
                foreach (StockOrderDetail detail in details)
                {
                    detail.StockOrder = this;
                }
            }
        }
        #endregion

        #region 获取单据明细 —— StockOrderDetail GetDetail(Guid detailId)
        /// <summary>
        /// 获取单据明细
        /// </summary>
        /// <param name="detailId">单据明细Id</param>
        /// <returns>单据明细</returns>
        public StockOrderDetail GetDetail(Guid detailId)
        {
            StockOrderDetail detail = this.Details.SingleOrDefault(x => x.Id == detailId);

            #region # 验证

            if (detail == null)
            {
                throw new NullReferenceException($"Id为\"{detailId}\"的单据明细不存在！");
            }

            #endregion

            return detail;
        }
        #endregion

        #region 提交审核 —— void Submit(string submitterAccount...
        /// <summary>
        /// 提交审核
        /// </summary>
        /// <param name="submitterAccount">提审人账号</param>
        /// <param name="submitterName">提审人姓名</param>
        public void Submit(string submitterAccount, string submitterName)
        {
            this.DoSubmit(submitterAccount, submitterName);
        }
        #endregion

        #region 审核 —— void Check(bool passed, string checkedRemark...
        /// <summary>
        /// 审核
        /// </summary>
        /// <param name="passed">是否通过</param>
        /// <param name="checkedRemark">审核意见</param>
        /// <param name="checkedAccount">审核人账号</param>
        /// <param name="checkedName">审核人姓名</param>
        public void Check(bool passed, string checkedRemark, string checkedAccount, string checkedName)
        {
            this.DoCheck(passed, checkedRemark, checkedAccount, checkedName);
        }
        #endregion

        #region 清空单据明细 —— void ClearDetails()
        /// <summary>
        /// 清空单据明细
        /// </summary>
        private void ClearDetails()
        {
            foreach (StockOrderDetail detail in this.Details.ToArray())
            {
                this.Details.Remove(detail);
            }
        }
        #endregion

        #region 初始化关键字 —— void InitKeywords()
        /// <summary>
        /// 初始化关键字
        /// </summary>
        private void InitKeywords()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(base.Number);
            builder.Append(base.Name);
            builder.Append(this.Description);

            base.SetKeywords(builder.ToString());
        }
        #endregion

        #endregion
    }
}
